package com.gitee.wsl.service.task.listener

import com.gitee.wsl.service.task.scope.TaskScope

interface TaskListener<SCOPE: TaskScope>{

    fun onPending(pendingFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onConnect(connectFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onProgress(progressFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onRetry(retryFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onPaused(pausedFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onError(errorFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onCompleted(completeFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onCancel(cancelFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun onDelete(deleteFun: SCOPE.()->Unit): TaskListener<SCOPE>

    fun warpAdapter(adapter: AbstractTaskListener<SCOPE>)

    fun firePending(scope: SCOPE)

    fun fireConnect(scope: SCOPE)

    fun fireProgress(scope: SCOPE)

    fun fireRetry(scope: SCOPE)

    fun firePaused(scope: SCOPE)

    fun fireError(scope: SCOPE)

    fun fireCompleted(scope: SCOPE)

    fun fireCancel(scope: SCOPE)

    fun fireDelete(scope: SCOPE)
}

abstract class AbstractTaskListener<SCOPE: TaskScope>(adapter: AbstractTaskListener<SCOPE>?=null) :
    TaskListener<SCOPE> {

    init {
        adapter?.let {
            warpAdapter(it)
        }
    }

    var pendingFun:(SCOPE.()->Unit)?=null

    var connectFun:(SCOPE.()->Unit)?=null

    var progressFun:(SCOPE.()->Unit)?=null

    var retryFun:(SCOPE.()->Unit)?=null

    var pausedFun:(SCOPE.()->Unit)?=null

    var errorFun:(SCOPE.()->Unit)?=null

    var completeFun:(SCOPE.()->Unit)?=null

    var cancelFun:(SCOPE.()->Unit)?=null

    var deleteFun:(SCOPE.()->Unit)?=null

    override fun onPending(pendingFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.pendingFun=pendingFun
        return this
    }

    override fun onConnect(connectFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.connectFun=connectFun
        return this
    }

    override fun onProgress(progressFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.progressFun=progressFun
        return this
    }

    override fun onRetry(retryFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.retryFun=retryFun
        return this
    }

    override fun onPaused(pausedFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.pausedFun=pausedFun
        return this
    }

    override fun onError(errorFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.errorFun=errorFun
        return this
    }

    override fun onCompleted(completeFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.completeFun=completeFun
        return this
    }

    override fun onCancel(cancelFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.cancelFun=cancelFun
        return this
    }

    override fun onDelete(deleteFun: SCOPE.() -> Unit): TaskListener<SCOPE> {
        this.deleteFun=deleteFun
        return this
    }

    override fun warpAdapter(adapter: AbstractTaskListener<SCOPE>){
        pendingFun = adapter.pausedFun

        connectFun = adapter.connectFun

        progressFun = adapter.progressFun

        retryFun = adapter.retryFun

        pausedFun = adapter.pausedFun

        errorFun = adapter.errorFun

        completeFun = adapter.completeFun

        cancelFun = adapter.cancelFun

        deleteFun = adapter.deleteFun
    }

    override fun firePending(scope: SCOPE) {
       pendingFun?.invoke(scope)
    }

    override fun fireConnect(scope: SCOPE) {
        connectFun?.invoke(scope)
    }

    override fun fireProgress(scope: SCOPE) {
        progressFun?.invoke(scope)
    }

    override fun fireRetry(scope: SCOPE) {
        retryFun?.invoke(scope)
    }

    override fun firePaused(scope: SCOPE) {
        pausedFun?.invoke(scope)
    }

    override fun fireError(scope: SCOPE) {
        errorFun?.invoke(scope)
    }

    override fun fireCompleted(scope: SCOPE) {
       completeFun?.invoke(scope)
    }

    override fun fireCancel(scope: SCOPE) {
        cancelFun?.invoke(scope)
    }

    override fun fireDelete(scope: SCOPE) {
        deleteFun?.invoke(scope)
    }

}